#include "EquationSolver.cpp"
using namespace std;

// function prepared for test
double f1(double x) { return 1 / x - tan(x); }
double f2(double x) { return 1 / x - pow(2, x); }
double f3(double x) { return pow(2, -x) + pow(M_E, x) + 2 * cos(x) - 6; }
double f4(double x) { return (pow(x, 3) + 4 * pow(x, 2) + 3 * x + 5) / (2 * pow(x, 3) - 9 * pow(x, 2) + 18 * x - 2); }

double f5(double x) { return x - tan(x); }
double df5(double x) { return 1 - 1 / pow(cos(x), 2); }

double f6(double x) { return sin(x / 2) - 1; }
double f7(double x) { return pow(M_E, x) - tan(x); }
double f8(double x) { return pow(x, 3) - 12 * pow(x, 2) + 3 * x + 1; }

double f9(double h)
{
    double L = 10, r = 1, r2 = r * r, V = 12.4;
    return L * (0.5 * M_PI * r2 - r2 * asin(h / r) - h * pow(r2 - h * h, 1 / 2)) - V;
}
double df9(double h)
{
    double L = 10, r = 1;
    return -2 * L * pow(r * r - h * h, 1 / 2);
}

double f10(double a)
{
    double l = 89, h = 49, D = 55, b = 11.5 / 180 * M_PI;
    double A = l * sin(b), B = l * cos(b), C = (h + 0.5 * D) * sin(b) - 0.5 * D * tan(b), E = (h + 0.5 * D) * cos(b) - 0.5 * D;
    return A * sin(a / 180 * M_PI) * cos(a / 180 * M_PI) + B * pow(sin(a / 180 * M_PI), 2) - C * cos(a / 180 * M_PI) - E * sin(a / 180 * M_PI);
}
double df10(double a)
{
    double l = 89, h = 49, D = 55, b = 11.5 / 180 * M_PI;
    double A = l * sin(b), B = l * cos(b), C = (h + 0.5 * D) * sin(b) - 0.5 * D * tan(b), E = (h + 0.5 * D) * cos(b) - 0.5 * D;
    return (A * (pow(cos(a / 180 * M_PI), 2) - pow(sin(a / 180 * M_PI), 2)) + B * 2 * sin(a / 180 * M_PI) * cos(a / 180 * M_PI) + C * sin(a / 180 * M_PI) - E * cos(a / 180 * M_PI)) / 180 * M_PI;
}
double f11(double a)
{
    double l = 89, h = 49, D = 30, b = 11.5 / 180 * M_PI;
    double A = l * sin(b), B = l * cos(b), C = (h + 0.5 * D) * sin(b) - 0.5 * D * tan(b), E = (h + 0.5 * D) * cos(b) - 0.5 * D;
    return A * sin(a / 180 * M_PI) * cos(a / 180 * M_PI) + B * pow(sin(a / 180 * M_PI), 2) - C * cos(a / 180 * M_PI) - E * sin(a / 180 * M_PI);
}
double df11(double a)
{
    double l = 89, h = 49, D = 30, b = 11.5 / 180 * M_PI;
    double A = l * sin(b), B = l * cos(b), C = (h + 0.5 * D) * sin(b) - 0.5 * D * tan(b), E = (h + 0.5 * D) * cos(b) - 0.5 * D;
    return (A * (pow(cos(a / 180 * M_PI), 2) - pow(sin(a / 180 * M_PI), 2)) + B * 2 * sin(a / 180 * M_PI) * cos(a / 180 * M_PI) + C * sin(a / 180 * M_PI) - E * cos(a / 180 * M_PI)) / 180 * M_PI;
}

int main()
{
    cout << "problem B:" << endl;
    BisectionMethod t1{f1, 0.001, M_PI / 2 - 0.001};
    t1.solve();
    t1.print();
    t1 = BisectionMethod{f2, 0.001, 1};
    t1.solve();
    t1.print();
    t1 = BisectionMethod{f3, 1, 3};
    t1.solve();
    t1.print();
    // zero not exists betreen [0,4],which will cause exit
    // t1 = BisectionMethod{f4, 0, 4};
    // t1.solve();
    // t1.print();

    cout << "problem C:" << endl;
    NewtonMethod t2{f5, df5, 4.5};
    t2.solve();
    t2.print();
    t2 = NewtonMethod{f5, df5, 7.7};
    t2.solve();
    t2.print();

    cout << "problem D:" << endl;
    SecantMethod t3{f6, 0, M_PI / 2};
    t3.solve();
    t3.print();
    t3 = SecantMethod{f7, 1, 1.4};
    t3.solve();
    t3.print();
    t3 = SecantMethod{f8, 0, -0.5};
    t3.solve();
    t3.print();

    cout << "problem E:" << endl;
    t1 = BisectionMethod{f9, 0, 1};
    t1.solve();
    t1.print();
    t2 = NewtonMethod{f9, df9, 0.5};
    t2.solve();
    t2.print();
    t3 = SecantMethod{f9, 0, 0.5};
    t3.solve();
    t3.print();

    cout << "problem F:" << endl;
    t2 = NewtonMethod{f10, df10, 33};
    t2.solve();
    t2.print();
    t2 = NewtonMethod{f11, df11, 33};
    t2.solve();
    t2.print();
    t3 = SecantMethod{f10, 0, 30};
    t3.solve();
    t3.print();
    t3 = SecantMethod{f10, 0, 180};
    t3.solve();
    t3.print();
}